﻿using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Logging;
using PetaPoco;
using PmSoft;
using PmSoft.ApplicationContext;
using PmSoft.Caching;
using PmSoft.DBContext;
using PmSoft.Entity;
using PmSoft.Repositories;
using PmSoft.Utilities;

namespace Modules.Corp.Repositories
{
    [UseDI(ServiceLifetime.Scoped)]
    public class CorpInfoRepository : Repository<CorpInfo, DefaultDbContext>
    {
        private readonly ILogger logger;

        public CorpInfoRepository(DefaultDbContext dbContext, IApplicationContext applicationContext, ILogger<CorpInfoRepository> logger)
            : base(dbContext, applicationContext)
        {
            this.logger = logger;
        }

        /// <summary>
        /// 重写插入
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        public override object Insert(CorpInfo entity)
        {

            Sql sql = Sql.Builder;
            sql.Select("corp_id")
                .From("corp")
                .Where("code=@0", entity.Code);

            int id = DbContext.FirstOrDefault<int>(sql);
            if (id > 0)
            {
                entity.IsDeleted = false;
                entity.CorpId = id;
                base.Update(entity);
                return entity;
            }
            else
                return base.Insert(entity);
        }

        /// <summary>
        /// 企业是否存在
        /// </summary>
        /// <param name="code"></param>
        /// <returns></returns>
        public bool CodeExists(string code)
        {
            return DbContext.Exists<CorpInfo>("code=@0 AND is_deleted=0", code, 审核状态.审核通过);
        }

        /// <summary>
        /// 更新默认管理的项目ID
        /// </summary>
        /// <param name="manager"></param>
        /// <param name="projectId"></param>
        /// <returns></returns>
        public bool UpdateDefaultProjectId(CorpInfo corpInfo, int projectId)
        {
            if (corpInfo == null)
                return false;
            var sql_update = Sql.Builder;
            sql_update.Append("Update corp SET project_id = @0 where corp_id = @1", projectId, corpInfo.CorpId);//局部更新数据库
            int affectCount = DbContext.Execute(sql_update);
            if (affectCount > 0)
            {
                corpInfo.ProjectId = projectId;
                base.OnUpdated(corpInfo);//更新内存数据
                return true;
            }
            return false;
        }

        public int? GetCorpId(string corpCode)
        {
            Sql sql = Sql.Builder.Select("corp_id").From("corp").Where("code=@0 AND is_deleted=0", corpCode);
            return DbContext.FirstOrDefault<int?>(sql);
        }

        public CorpInfo? GetCorpInfo(string corpCode)
        {
            var id = GetCorpId(corpCode);
            if (id.HasValue && id > 0)
                return Get(id);
            return null;
        }

        public IEnumerable<CorpInfo> GetCorpInfos(IEnumerable<string> corpCodes)
        {
            Sql sql = Sql.Builder.Select("corp_id").From("corp").Where("is_deleted=0 AND code in (@0)", corpCodes);
            var id = DbContext.Fetch<int>(sql);

            return PopulateEntitiesByEntityIds(id);
        }

        public IPagedList<CorpInfo> GetCorpInfos(CorpInfoQuery query, int pageIndex, int pageSize, IEnumerable<int?> corpIds = null)
        {
            Sql sql = Sql.Builder;
            sql.Select("corp_id")
                .From("corp")
                .Where("is_deleted=0");
            if (!string.IsNullOrEmpty(query.Keywords))
                sql.Where("(name Like @0 or code Like @0 or legalman Like @0)", "%" + StringUtility.StripSQLInjection(query.Keywords) + "%");
            if (query.ProjectId.HasValue)
                sql.Where("project_id=@0", query.ProjectId.Value);
            if (query.ProvinceCode.HasValue)
                sql.Where("province_code=@0", query.ProvinceCode);
            if (query.CityCode.HasValue)
                sql.Where("city_code=@0", query.CityCode);
            if (query.AreaCode.HasValue)
                sql.Where("area_code=@0", query.AreaCode);
            if (query.HasAuth.HasValue)
                sql.Where("has_auth=@0", query.HasAuth.Value ? 1 : 0);
            if (query.CheckStatus.HasValue)
                sql.Where("check_status=@0", query.CheckStatus);
            if (query.CorpType.HasValue)
                sql.Where("corp_type=@0", query.CorpType.Value);
            if (corpIds != null && corpIds.Any())
            {
                sql.Where("corp_id IN (@0)", corpIds);
            }
            sql.OrderBy("create_time DESC");
            var result = GetPagingEntities(pageSize, pageIndex, sql);
            return result;
        }

        public IPagedList<CorpInfo> GetCorpInfosByProjectId(CorpInfoQuery query, int pageIndex, int pageSize)
        {
            Sql sql = Sql.Builder;
            sql.Select("corp.corp_id")
                .From("corp").InnerJoin("project_corp as pc on pc.corp_id=corp.corp_id");
            if (!string.IsNullOrEmpty(query.Keywords))
                sql.Where("(name Like @0 or code Like @0 or legalman Like @0)", "%" + StringUtility.StripSQLInjection(query.Keywords) + "%");
            if (query.ProvinceCode.HasValue)
                sql.Where("province_code=@0", query.ProvinceCode);
            if (query.CityCode.HasValue)
                sql.Where("city_code=@0", query.CityCode);
            if (query.AreaCode.HasValue)
                sql.Where("area_code=@0", query.AreaCode);
            if (query.ProjectId.HasValue)
                sql.Where("pc.project_id=@0", query.ProjectId);
            sql.Where("pc.role!=8 and pc.role!=7");//取消参建单位为建设单位和监理的情况
            sql.OrderBy("pc.role desc,pc.create_time DESC");
            var result = GetPagingEntities(pageSize, pageIndex, sql);
            return result;
        }

        public IEnumerable<CorpInfo> GetCorpsByProjectId(int? projectId)
        {
            if (!projectId.HasValue)
                return Enumerable.Empty<CorpInfo>();
            int areaVersion = EntityCacheService.GetAreaVersion("ProjectId", projectId);
            return GetTopEntities(1000, CachingExpirationType.ObjectCollection, () =>
            {
                return $"CorpsByProjectId:{projectId}:{areaVersion}";
            }, () =>
            {
                Sql sql = Sql.Builder
                .Select("corp_id")
                .From("corp")
                .Where("corp_id in (select corp_id from project_corp where project_id=@0)", projectId);
                return sql;
            });
        }

        /// <summary>
        /// 获取不能匹配上当前企业Id的所有企业
        /// </summary>
        /// <param name="corpIds"></param>
        /// <returns></returns>
        internal IEnumerable<CorpInfo> GetCorpInfosNotCorpIds(IEnumerable<int> corpIds)
        {
            Sql sql = Sql.Builder;
            sql.Select("corp_id")
                .From("corp").Where("corp_id not in (@0) and check_status =@1", corpIds, 审核状态.审核通过);
            return PopulateEntitiesByEntityIds(DbContext.FetchFirstColumn<int>(sql));
        }

        /// <summary>
        /// 搜索企业
        /// </summary>
        /// <param name="keywords"></param>
        /// <returns></returns>
        public IEnumerable<CorpInfo> SearchCorps(string keywords, int limit = 10)
        {
            if (string.IsNullOrEmpty(keywords))
                return Enumerable.Empty<CorpInfo>();
            if (limit > 100)
                limit = 100;
            Sql sql = Sql.Builder;
            sql.Select("corp_id")
                .From("corp").Where("MATCH (name) AGAINST (@0 IN BOOLEAN MODE)", "*" + StringUtility.StripSQLInjection(keywords) + "*").Append($"LIMIT {limit}");
            return PopulateEntitiesByEntityIds(DbContext.FetchFirstColumn<int>(sql));
        }

    }
}